using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace ParserGenerator.TableCompression
{
    [Serializable]
    public sealed class CompactTableRowBuilder
    {
        private readonly int _columns;
        private readonly HashSet<int> _used = new HashSet<int>();
        public int Number { get; }

        [NonSerialized]
        private ReadOnlyCollection<CompactTableCell> _cellsWrapper;
        private readonly List<CompactTableCell> _cells;
        public ReadOnlyCollection<CompactTableCell> Cells
        {
            get
            {
                if (_cellsWrapper == null)
                    _cellsWrapper = _cells.AsReadOnly();
                return _cellsWrapper;
            }
        }

        internal CompactTableRowBuilder(int number, int columns)
        {
            if (number < 0)
                throw new ArgumentOutOfRangeException(nameof(number), SR.NumberMustBeNonNegative);
            if (columns <= 0)
                throw new ArgumentOutOfRangeException(nameof(columns), SR.ColumnsMustBePositive);
            Number = number;
            _columns = columns;
            _cells = new List<CompactTableCell>();
        }

        public void Add(int column, int value)
        {
            if (column < 0)
                throw new ArgumentOutOfRangeException(nameof(column), SR.ColumnMustBeNonNegative);
            if (column >= _columns)
                throw new ArgumentOutOfRangeException(nameof(column), SR.ColumnOutOfRange);
            if (value < 0)
                throw new ArgumentOutOfRangeException(nameof(value), SR.ValueMustBeNonNegative);
            if (!_used.Add(column))
            {
                string message = string.Format(SR.ValueOfCellSpecified, Number, column);
                throw new ArgumentException(message);
            }
            _cells.Add(new CompactTableCell(column, value));
        }

        public void Clear()
        {
            _cells.Clear();
            _used.Clear();
        }

        public sealed override string ToString()
        {
            return Number + ": " + string.Join(", ", _cells);
        }
    }
}
